/*
 * Copyright (c) 2011, Andrew Cole
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

package net.andycole.xmiparser.model;

import java.io.File;
import java.util.Map;
import java.util.Map.Entry;

import com.adobe.ac.pmd.files.impl.FileUtils;
import com.adobe.ac.pmd.files.IAs3File;
import com.adobe.ac.pmd.files.IFlexFile;
import com.adobe.ac.pmd.files.IMxmlFile;

import net.sourceforge.pmd.PMDException;

import org.apache.log4j.Logger;

import net.andycole.xmiparser.transfer.TransferClass;
import net.andycole.xmiparser.parser.ASFileParser;
import net.andycole.xmiparser.parser.MXMLFileParser;
import net.andycole.xmiparser.parser.IASParser;


/**
 *
 * @author andy
 */
public class ModelBuilder
{
   private String parentDir;
   private IModel model;

   private Logger LOG = Logger.getLogger(ModelBuilder.class);

   /**
    * Constructor taking the directory location of the root package of the
    * sources to import and the metadata model to add content to.
    * @param parentDir
    * @param model
    */
   public ModelBuilder(String parentDir, IModel model)
   {
      super();
      this.parentDir = parentDir;
      this.model = model;
   }

   public IModel getModel()
   {
      return model;
   }

   public void build()
   {
      File baseDir = new File(parentDir);
      Map< String, IFlexFile > files;
      try
      {
         files = FileUtils.computeFilesList(baseDir, null, "", null);

         model.startTransaction(true);
         buildPackages(files);
         model.endTransaction();
      }
      catch (PMDException exception)
      {
//         System.err.println("Exception occurred while gathering " +
//                            "files for conversion. " +
//                            exception.getMessage());
         LOG.error("Exception occurred while gathering " +
                   "files for conversion. " +
                   exception.getMessage(), exception);
      }
   }

   private void buildPackages(final Map<String, IFlexFile> files)
   {
      int count = 0;
      for ( final Entry< String, IFlexFile > fileEntry : files.entrySet() )
      {
         final IFlexFile file = fileEntry.getValue();

         IASParser parser = null;

         TransferClass classInfo = null;
         try
         {
            if ( file instanceof IAs3File )
            {
               parser = new ASFileParser();
               classInfo = parser.parse( file.getFilePath(),
                                         file.getPackageName());
            }
            else
            {
               parser = new MXMLFileParser();
               classInfo = parser.parse( file.getFilePath(),
                                         file.getPackageName(),
                                         ( ( IMxmlFile ) file ).getScriptBlock() );
            }

            // add each parsed class to the model
            addClassToModel(classInfo);
         }
         catch(Exception error)
         {
//            System.err.println("Could not parse file "+file.getFilePath()+
//                               ": " + error.getMessage());
            LOG.warn("Could not parse file "+file.getFilePath()+
                     ": " + error.getMessage());
         }
         //System.out.println("Parsed "+ ++count +" files");
         LOG.info("Parsed "+ ++count +" files");
      }
   }

   private void addClassToModel(TransferClass classInfo)
   {
      try
      {
         model.addClass(classInfo);
      }
      catch(Exception error)
      {
//         System.err.println("Could not add class "+classInfo.getQualifiedClassName()+
//                            " to model: " + error + " " + error.getMessage());
         LOG.warn("Could not add class "+classInfo.getQualifiedClassName()+
                  " to model: " + error + " " + error.getMessage());
      }
   }
}
